
package org.javahispano.javacup.tacticas_aceptadas.ijb.PistolerosDeGilead;

import java.util.LinkedList;
import org.javahispano.javacup.modelo.*;
import java.util.List;
import java.util.Random;

public class PistolerosDeGileadDos implements Tactica {

        Posicion alineacion1[]=new Posicion[]{
        new Posicion(0.2595419847328244,-50.41044776119403),
        new Posicion(-7.37062937062937,-35.39592760180996),
        new Posicion(7.37062937062937,-35.63348416289593),
        new Posicion(22.825174825174827,-28.744343891402718),
        new Posicion(-23.538461538461537,-28.744343891402718),
        new Posicion(0.0,-12.352941176470589),
        new Posicion(21.16083916083916,8.076923076923077),
        new Posicion(-21.636363636363637,8.076923076923077),
        new Posicion(-0.23776223776223776,14.490950226244346),
        new Posicion(-10.461538461538462,29.93212669683258),
        new Posicion(9.986013986013985,30.407239819004527)
    };

    Posicion alineacion2[]=new Posicion[]{
        new Posicion(0.2595419847328244,-50.41044776119403),
        new Posicion(-7.608391608391608,-35.63348416289593),
        new Posicion(7.846153846153847,-35.63348416289593),
        new Posicion(20.685314685314687,-28.98190045248869),
        new Posicion(-21.3986013986014,-28.744343891402718),
        new Posicion(0.0,-28.744343891402718),
        new Posicion(16.405594405594407,-13.065610859728507),
        new Posicion(-15.93006993006993,-13.065610859728507),
        new Posicion(-0.23776223776223776,-19.004524886877828),
        new Posicion(-8.083916083916083,-4.98868778280543),
        new Posicion(8.083916083916083,-5.226244343891403)
    };

    Posicion alineacion3[]=new Posicion[]{
        new Posicion(0.2595419847328244,-50.41044776119403),
        new Posicion(-8.083916083916083,-35.39592760180996),
        new Posicion(7.846153846153847,-35.63348416289593),
        new Posicion(27.58041958041958,-22.805429864253394),
        new Posicion(-28.293706293706293,-23.993212669683256),
        new Posicion(-0.23776223776223776,-25.418552036199095),
        new Posicion(19.734265734265733,-5.701357466063349),
        new Posicion(-21.636363636363637,-5.701357466063349),
        new Posicion(-0.4755244755244755,-10.214932126696834),
        new Posicion(-2.13986013986014,-0.23755656108597287),
        new Posicion(0.4755244755244755,-0.47511312217194573)
    };
    
    Posicion alineacion4[]=new Posicion[]{
        new Posicion(0.2595419847328244,-50.41044776119403),
        new Posicion(-11.16030534351145,-35.78358208955224),
        new Posicion(12.717557251908397,-35.26119402985075),
        new Posicion(23.062937062937063,-28.744343891402718),
        new Posicion(-22.349650349650346,-28.98190045248869),
        new Posicion(-0.7132867132867133,-30.16968325791855),
        new Posicion(14.97902097902098,-19.717194570135746),
        new Posicion(-14.265734265734267,-19.479638009049776),
        new Posicion(0.0,-9.264705882352942),
        new Posicion(-11.888111888111888,9.97737556561086),
        new Posicion(10.461538461538462,20.90497737556561)
    };



    public Posicion[] getPosicionSaca(SituacionPartido sp) {
    return alineacion3;
    }

    public Posicion[] getPosicionRecive(SituacionPartido sp) {
    return alineacion2;
    } 

    TacticaDetalle detalle=new PistolerosDeGileadDetalle();
    public TacticaDetalle getDetalle() {
        return detalle;
    }
    
    int contadorDeIteracion = 0, contador0 = 0;
    double[] velocidadContrarios = new double[11];
    double[] fuerzaContrarios = new double[11];
    double[] precisionContrarios = new double[11];
    Posicion[] posicionContrarios = new Posicion[11];
    int contadorPresion = 0;
    int STEVEN = 3;
    int DINKY = 4;
    int ALAIN = 6;
    int CUTHBERT = 7;
    
    public double getFuerza(int n,SituacionPartido sp) {
        return sp.detalleMisJugadores()[n].getRemate();
    }

    public double getVelocidad(int n,SituacionPartido sp) {
        return sp.detalleMisJugadores()[n].getVelocidad();
    }
    
    public double getPrecision(int n,SituacionPartido sp){
        return sp.detalleMisJugadores()[n].getPresicion();
    }

    public double getXInicial(int n,SituacionPartido sp) {
        return sp.misJugadores()[n].getX();
    }

    public double getYInicial(int n,SituacionPartido sp) {
        return sp.misJugadores()[n].getY();
    }
    
    
    Random rand = new Random();
    LinkedList<Comando> comandos = new LinkedList<Comando>();

    public List<Comando> ejecutar(SituacionPartido sp) {
       
        comandos.clear();
        
        if(comparadorPosiciones(sp)){
            contadorPresion++;
        }else{
            contadorPresion--;
        }
        
        if((sp.golesPropios() > sp.golesRival() + 1) && contadorPresion < 3){
            for (int i = 0; i < 11; i++) {
                comandos.add(new ComandoIrA(i, alineacion4[i]));
            }
        }else{
           for (int i = 0; i < 11; i++) {
                comandos.add(new ComandoIrA(i, alineacion1[i]));
            } 
        }
       
        //obtiene el indice del jugador mas cercano al balon
        int indMasCercano = sp.balon().indiceMasCercano(sp.misJugadores());
        //el jugador mas cercano sigue al balon
        if(indMasCercano == 0 && !dentroArea(sp.balon())){
            int[] indMasCercanos = sp.balon().indicesMasCercanos(sp.misJugadores());
            comandos.add(new ComandoIrA(indMasCercanos[1], sp.balon()));
        }else{
             comandos.add(new ComandoIrA(indMasCercano, sp.balon()));
        }
        calcularPase(sp,indMasCercano);
        
        double porx = Math.max(-3, sp.balon().getX());
        porx = Math.min(3, porx);
        
        if(!sp.saco()){
            comandos.add(new ComandoIrA(0, new Posicion(porx,-51.5)));
        }
        
        //El portero va a por la pelota si ésta se encuentra en el área pequeña
        if(sp.balon().getY() < -46.5 ){
            comandos.add(new ComandoIrA(0, sp.balon()));
        }
        
        //Asignamos al vector PosicionContrarios la posición que tienen en esta iteración
        posicionContrarios = sp.rivales();
        
        if(contadorPresion > 3){
            //nos están haciendo defensa al hombre, excepto el portero y los delanteros, todos chutan a saco y
            //no intentan sacar el balón controlado
            for (int i = 1; i < 6; i++) {
                comandos.add(new ComandoGolpearBalon(i, Constantes.centroArcoSup, 1, true));
            }
        }
        
        contadorDeIteracion++;
        return comandos;
    }
    
    private void calcularPase(SituacionPartido sp, int indMasCercano)
    {
        //identificamos al jugador portero
        boolean esPortero;
        int idPortero = 0;
        for (int i = 0; i < 11; i++) {
            esPortero = sp.detalleMisJugadores()[i].esPortero();
            if(esPortero){
                idPortero = i;
                break;
            }
        }
        
        //obtiene un arreglo con los indices de los jugadores que pueden rematar
        int rematan[] = sp.puedenRematar();
        //recorre los jugadores que pueden rematar
        for (int i : rematan) {
            //obtiene los jugadores mas cercanos, al jugador que puede rematar
            int[] cercanos = sp.misJugadores()[indMasCercano].indicesMasCercanos(sp.misJugadores(),idPortero);
            //encontro un pase en falso
            boolean pase = false;
            boolean alto;
            //recorre los jugadores desde el mas cercano al mas lejano
            for (int j = 1; !pase && j < cercanos.length; j++) {
                //si el jugador es distinto al jugador que remata y el jugador esta mas adelantado
                if (sp.misJugadores()[i].getY() < sp.misJugadores()[cercanos[j]].getY()) {
                    if(cercanos[j] != 0){
                        //dar pase al jugador mas cercano que este en posicion mas ofensiva
                        //Posicion posJugador = sp.misJugadores()[cercanos[j]];
                        Posicion posJugadorRecibe = sp.misJugadores()[cercanos[j]];
                        Posicion posJugadorEnvia = sp.misJugadores()[indMasCercano];
                        boolean distanciaOK = validarDistanciaRivales(sp,posJugadorRecibe,posJugadorEnvia);
                        if(distanciaOK && posJugadorEnvia.distancia(posJugadorRecibe) < 30){
                            comandos.add(new ComandoGolpearBalon(indMasCercano, sp.misJugadores()[cercanos[j]], 1, false));
                            //encontro un pase por lo menos
                            pase = true;
                            //System.out.println("pase tipo 1 OK");
                        }
                    }
                }
            }
            //si no encontro ningun pase
            if (!pase) {
                if(cercanos[1] == 0){
                    //si el que tengo más cerca es el portero y no hay posibilidad de pase seguro, la tiro lo más lejos posible
                    comandos.add(new ComandoGolpearBalon(indMasCercano, sp.misJugadores()[cercanos[cercanos.length - 2]], 1, true));
                }else{
                    if(sp.balon().getY() > (Constantes.LARGO_CAMPO_JUEGO * (2/3))){
                        Posicion posJugadorEnvia = sp.misJugadores()[indMasCercano];
                        if(calcularIntersecHastaPorteria(sp, posJugadorEnvia)){
                            for (int j = 1; !pase && j < cercanos.length; j++) {
                                 //si el jugador es distinto al jugador que remata y el jugador esta mas adelantado
                                if (sp.misJugadores()[i].getY() < sp.misJugadores()[cercanos[j]].getY()) {
                                    if(cercanos[j] != 0){
                                        //dar pase al jugador mas cercano que este en posicion mas ofensiva
                                        Posicion posJugadorRecibe = sp.misJugadores()[cercanos[j]];
                                        if(!calcularIntersecHastaCompañero(sp,posJugadorEnvia,posJugadorRecibe)){
                                            comandos.add(new ComandoGolpearBalon(indMasCercano, sp.misJugadores()[cercanos[j]], 1, false));
                                            pase = true;
                                            //System.out.println("pase tipo 2 OK");
                                        }
                                    }
                                }
                                else{
                                   if(cercanos[j] != 0){
                                        //dar pase al jugador libre aunque no esté más adelantado
                                        Posicion posJugadorRecibe = sp.misJugadores()[cercanos[j]];
                                        if(!calcularIntersecHastaCompañero(sp,posJugadorEnvia,posJugadorRecibe)){
                                            comandos.add(new ComandoGolpearBalon(indMasCercano, sp.misJugadores()[cercanos[j]], 1, false));
                                            pase = true;
                                            //System.out.println("pase tipo 2.5 OK");
                                        }
                                    } 
                                }
                            }
                            if(!pase){
                                for (int j = 1; !pase && j < cercanos.length; j++) {
                                     //si el jugador es distinto al jugador que remata y el jugador esta mas adelantado
                                    if (sp.misJugadores()[i].getY() < sp.misJugadores()[cercanos[j]].getY()) {
                                        if(cercanos[j] != 0){
                                            //dar pase al jugador mas cercano que este en posicion mas ofensiva
                                            comandos.add(new ComandoGolpearBalon(indMasCercano, sp.misJugadores()[cercanos[j]], 1, false));
                                            pase = true;
                                            //System.out.println("pase tipo 3 OK");

                                        }
                                    }else{
                                       if(cercanos[j] != 0){
                                            //dar pase al jugador libre aunque no esté más adelantado
                                            Posicion posJugadorRecibe = sp.misJugadores()[cercanos[j]];
                                            comandos.add(new ComandoGolpearBalon(indMasCercano, sp.misJugadores()[cercanos[j]], 1, false));
                                            pase = true;
                                            //System.out.println("pase tipo 3.5 OK");
                                        } 
                                    }
                                }
                            }
                            if(!pase){
                                //System.out.println("conduccion 1");
                                if(indMasCercano == STEVEN || indMasCercano == ALAIN){
                                    Posicion posJugador = sp.misJugadores()[indMasCercano];
                                    if(posJugador.distancia(new Posicion(17.0,40.0)) < 5){
                                        comandos.add(new ComandoGolpearBalon(indMasCercano, Constantes.centroArcoSup, 1, 20));
                                    }else{
                                        comandos.add(new ComandoGolpearBalon(indMasCercano));
                                        comandos.add(new ComandoIrA(indMasCercano, new Posicion(17.0,40.0))); 
                                    }
                                }else if(indMasCercano == DINKY || indMasCercano == CUTHBERT){
                                    Posicion posJugador = sp.misJugadores()[indMasCercano];
                                    if(posJugador.distancia(new Posicion(-17.0,40.0)) < 5){
                                        comandos.add(new ComandoGolpearBalon(indMasCercano, Constantes.centroArcoSup, 1, 20));
                                    }else{
                                        comandos.add(new ComandoGolpearBalon(indMasCercano));
                                        comandos.add(new ComandoIrA(indMasCercano, new Posicion(-17.0,40.0))); 
                                    }
                                }else{
                                    comandos.add(new ComandoGolpearBalon(indMasCercano));
                                    comandos.add(new ComandoIrA(indMasCercano, Constantes.penalSup)); 
                                }  
                                 
                            }
                        }else{
                            //System.out.println("conduccion 2");
                            if(indMasCercano == STEVEN || indMasCercano == ALAIN){
                                Posicion posJugador = sp.misJugadores()[indMasCercano];
                                if(posJugador.distancia(new Posicion(17.0,40.0)) < 5){
                                    comandos.add(new ComandoGolpearBalon(indMasCercano, Constantes.centroArcoSup, 1, 20));
                                }else{
                                    comandos.add(new ComandoGolpearBalon(indMasCercano));
                                    comandos.add(new ComandoIrA(indMasCercano, new Posicion(17.0,40.0))); 
                                }
                            }else if(indMasCercano == DINKY || indMasCercano == CUTHBERT){
                                Posicion posJugador = sp.misJugadores()[indMasCercano];
                                if(posJugador.distancia(new Posicion(-17.0,40.0)) < 5){
                                    comandos.add(new ComandoGolpearBalon(indMasCercano, Constantes.centroArcoSup, 1, 20));
                                }else{
                                    comandos.add(new ComandoGolpearBalon(indMasCercano));
                                    comandos.add(new ComandoIrA(indMasCercano, new Posicion(-17.0,40.0))); 
                                }
                            }else{
                                comandos.add(new ComandoGolpearBalon(indMasCercano));
                                comandos.add(new ComandoIrA(indMasCercano, Constantes.penalSup)); 
                            }  
                        }
                    }else{
                        //System.out.println("conduccion 3");
                        comandos.add(new ComandoGolpearBalon(indMasCercano));
                        if(indMasCercano == STEVEN || indMasCercano == ALAIN){
                            comandos.add(new ComandoIrA(indMasCercano, new Posicion(17.0,40.0))); 
                        }else if(indMasCercano == DINKY || indMasCercano == CUTHBERT){
                            comandos.add(new ComandoIrA(indMasCercano, new Posicion(-17.0,40.0))); 
                        }else{
                            comandos.add(new ComandoIrA(indMasCercano, Constantes.penalSup)); 
                        }     
                    }
                }
            }
            //si el jugador que remata esta a menos de 30 metros del arco rival -> remata al arco
            if(sp.detalleMisJugadores()[i].getRemate() > 0.75){
                if (sp.misJugadores()[i].distancia(Constantes.centroArcoSup) < 30) {
                    comandos.add(new ComandoGolpearBalon(i, Constantes.centroArcoSup, 1, 20));
                }
            }else if(sp.detalleMisJugadores()[i].getRemate() > 0.5){
                if (sp.misJugadores()[i].distancia(Constantes.centroArcoSup) < 20) {
                    comandos.add(new ComandoGolpearBalon(i, Constantes.centroArcoSup, 1, 20));
                }
            }else{
                if (sp.misJugadores()[i].distancia(Constantes.centroArcoSup) < 15) {
                    comandos.add(new ComandoGolpearBalon(i, Constantes.centroArcoSup, 1, 20));
                }
            }
        }
        
        //si balon en el area grande, despejamos a saco
        if(sp.balon().getY() < -36.0 && 
                (sp.balon().getX() > -20.0 || sp.balon().getX() < 20.0)){
            if(sp.balon().getX() < 0){
                comandos.add(new ComandoGolpearBalon(indMasCercano, Constantes.cornerSupIzq, 1, true));
            }else{
              comandos.add(new ComandoGolpearBalon(indMasCercano, Constantes.cornerSupDer, 1, true));  
            }
        }
        
        
        //Portero siempre chuta lejos
        int[] cercanosPortero = sp.misJugadores()[0].indicesMasCercanos(sp.misJugadores(),idPortero);
        comandos.add(new ComandoGolpearBalon(0, sp.misJugadores()[cercanosPortero[cercanosPortero.length - 2]], 1, true));
    }
    
    public boolean validarDistanciaRivales(SituacionPartido sp, Posicion posJugadorRecibe, Posicion posJugadorEnvia)
    {
        Posicion[] rivales = sp.rivales();
        double distMenor = 999;
        for(Posicion i : rivales){
            double distJugadorRival = posJugadorRecibe.distancia(i);
            if(distJugadorRival < distMenor){
                distMenor = distJugadorRival;
            }
        }
        if(distMenor < 10){
            return false;
        }
        return true;
    }
    
    public boolean calcularIntersecHastaPorteria(SituacionPartido sp,Posicion posJugador){
        Posicion[] rivales = sp.rivales();
        for(Posicion i : rivales){
            double distJugadorRival = posJugador.distancia(i);
            Posicion intersec = Posicion.Interseccion(posJugador, Constantes.penalSup, posJugador, i);
            if(intersec != null && distJugadorRival < 10 && i.getY() > posJugador.getY()){
                return true;
            }
        }
        return false;
    }
    
    public boolean calcularIntersecHastaPosteDerecho(SituacionPartido sp,Posicion posJugador){
        Posicion[] rivales = sp.rivales();
        for(Posicion i : rivales){
            double distJugadorRival = posJugador.distancia(i);
            Posicion intersec = Posicion.Interseccion(posJugador, Constantes.posteDerArcoSup, posJugador, i);
            if(intersec != null && distJugadorRival < 10 && i.getY() > posJugador.getY()){
                return true;
            }
        }
        return false;
    }
    
    public boolean calcularIntersecHastaPosteIzquierdo(SituacionPartido sp,Posicion posJugador){
        Posicion[] rivales = sp.rivales();
        for(Posicion i : rivales){
            double distJugadorRival = posJugador.distancia(i);
            Posicion intersec = Posicion.Interseccion(posJugador, Constantes.posteIzqArcoSup, posJugador, i);
            if(intersec != null && distJugadorRival < 10 && i.getY() > posJugador.getY()){
                return true;
            }
        }
        return false;
    }
    
    public boolean calcularIntersecHastaCompañero(SituacionPartido sp,Posicion posJugadorEnvia,Posicion posJugadorRecibe){
        Posicion[] rivales = sp.rivales();
        for(Posicion i : rivales){
            Posicion intersec = Posicion.Interseccion(posJugadorEnvia, posJugadorRecibe, posJugadorEnvia, i);
            if(intersec != null && i.getY() > posJugadorEnvia.getY() && i.getY() != posJugadorRecibe.getY()){
                return true;
            }
        }
        return false;
    }
    
    
    /**Limita la posicion a estar dentro del campo de juego*/
    public boolean dentroArea(Posicion balon) {
        if(balon.getX() > Constantes.ANCHO_AREA_GRANDE || balon.getY() > Constantes.LARGO_AREA_GRANDE){
            return false;
        }
        return true;
    }
    
    public boolean comparadorPosiciones(SituacionPartido sp){
        Posicion[] rivales = sp.rivales();
        Posicion[] nuestros = sp.misJugadores();
        contadorPresion = 0;
        for(Posicion i : nuestros){
            double distMenor = 999;
            for(Posicion j : rivales){
                double distJugadores = i.distancia(j);
                if(distJugadores < distMenor){
                    distMenor = distJugadores;
                }
            }
            if(distMenor < 5){
                contadorPresion++;
            }
        }
        if(contadorPresion >= 7){
            return true;
        }
        return false;
    }
}